#include <wx/msgdlg.h>
#include <highgui.h>
#include "camclientframe.h"
#include "videothread.h"

#define WAIT_FOR_NEXT_FRAME 100

VideoThread::VideoThread(wxFrame * mainFrame, SocketClient * client) 
: wxThread() {
	this->client = client;
	this->readBuffer = 0;
	this->image = 0;
	this->frame = mainFrame;
}

wxThread::ExitCode VideoThread::Entry() {
	int buffSize = 4;
	int count = -1;
	char * buff = new char[buffSize];
	//receive width
	int imageWidth = 0;
	memset(buff, 0, buffSize);
	count = this->client->receiveData(buff, buffSize - 1);
	if (count != -1) {
		 imageWidth = atoi(buff);
	}
	//receive height
	int imageHeight = 0;
	memset(buff, 0, buffSize);
	count = this->client->receiveData(buff, buffSize - 1);
	if (count != -1) {
		imageHeight = atoi(buff);
	}
	delete [] buff;
	//create read stream buffer and image
	const int imageDepth = 8;
	const int countChannels = 3;
	int imageSize = imageWidth * imageHeight / 8 * imageDepth * countChannels;
	this->readBuffer = new char[MAX_PACKET_SIZE];
	this->image = cvCreateImage(cvSize(imageWidth, imageHeight), imageDepth, countChannels);
	//read camera card from server
	bool disconnected = false;
	while (!this->TestDestroy()) {
		strcpy(this->readBuffer, "getnextframe");
		count = this->client->sendData(this->readBuffer, strlen(this->readBuffer));
		if (count <= 0) { 
			disconnected = true;
			break;
		}
		//receive frame
		int recvBytes = 0;
		int diff = 0;
		while (recvBytes < imageSize) {
			diff = imageSize - recvBytes;
			count = this->client->receiveData(this->readBuffer, diff < MAX_PACKET_SIZE ? diff : MAX_PACKET_SIZE, 0);
			if (count <= 0) { 
				disconnected = true;
				break;
			}
			memcpy(this->image->imageData+recvBytes, this->readBuffer, count);
			recvBytes += count;
		}
		if (disconnected) {
			break;
		}
		Sleep(WAIT_FOR_NEXT_FRAME);
		//------------
	}

	if (disconnected) {
		CamClientFrame * clientFrame = ((CamClientFrame*)this->frame);
		wxCriticalSectionLocker enter(clientFrame->videoThreadCS);
		clientFrame->OnThreadCompletion();
	}
	return (wxThread::ExitCode)0;
}

VideoThread::~VideoThread() {
	/*CamClientFrame * clientFrame = ((CamClientFrame*)this->frame);
	wxCriticalSectionLocker enter(clientFrame->videoThreadCS);
	clientFrame->OnThreadCompletion();*/
}

void VideoThread::OnExit() {
	if (this->client) {
		delete this->client;
	}
	if (this->frame) {
		cvReleaseImage(&this->image);
	}
	if (this->readBuffer) {
		delete [] this->readBuffer;
	}
}

IplImage * VideoThread::GetImage() const {
	return this->image;
}
